import { showMessage } from '@/components/antd-comp/message'
import { BlockEnum } from '@/components/workflow/types'
import { cloneDeep } from 'lodash'
import { INPUT_CONSTRAINTS } from './components/InspectData'

// 查找所有能流动到target源头
export const findSources = (target, edges) => {
  const sources = new Set()
  const to_process = [target]

  while (to_process.length > 0) {
    const current = to_process.pop()
    for (const edge of edges) {
      if (edge.target === current) {
        const source = edge.source
        if (!sources.has(source)) {
          sources.add(source)
          to_process.push(source)
        }
      }
    }
  }

  return Array.from(sources)
}

// 判断是否支持单节点调试
export const canRunBySingle = (nodeType: BlockEnum) => {
  return (
    nodeType === BlockEnum.LLM ||
    nodeType === BlockEnum.KnowledgeRetrieval ||
    nodeType === BlockEnum.Code ||
    nodeType === BlockEnum.Tool ||
    nodeType === BlockEnum.Workflow ||
    nodeType === BlockEnum.Intend ||
    nodeType === BlockEnum.DocExtractor ||
    nodeType === BlockEnum.HttpRequest ||
    nodeType === BlockEnum.TextConcatenation
    //nodeType === BlockEnum.Iteration
  )
}

export const isStartOrEnd = (nodeType: BlockEnum) => {
  return nodeType === BlockEnum.Start || nodeType === BlockEnum.End || nodeType === BlockEnum.IterationStart 
  || nodeType === BlockEnum.IterationEnd || nodeType === BlockEnum.LoopStart || nodeType === BlockEnum.LoopEnd
}

export const noClose = (nodeType: BlockEnum) => {
  return nodeType === BlockEnum.Start || nodeType === BlockEnum.End || nodeType === BlockEnum.IterationEnd
}

export const noLeftHandle = (nodeType: BlockEnum) => {
  return nodeType === BlockEnum.Start  || nodeType === BlockEnum.IterationStart || nodeType === BlockEnum.LoopStart
}

export const noPanel = (nodeType: BlockEnum) => {
  return nodeType === BlockEnum.IterationStart || nodeType === BlockEnum.LoopStart
}

export const noNodeBody = (nodeType: BlockEnum) => {
  return nodeType === BlockEnum.IterationStart || nodeType === BlockEnum.LoopStart || nodeType === BlockEnum.LoopEnd 
}

export const noRightHandle = (nodeType: BlockEnum) => {
  return nodeType === BlockEnum.End || nodeType === BlockEnum.IfElse || nodeType === BlockEnum.Intend 
  || nodeType === BlockEnum.IterationEnd || nodeType === BlockEnum.LoopEnd
}

/* array 检查字段 */
export const checkArrayItems = (array, requiredFields) => {
  for (const item of array) {
    if (requiredFields.some(field => item.required && !item[field])) {
      return false
    }
  }
  return true
}

/* array 检查字段 */
export const checkDefaultRequiredArrayItems = (array, requiredFields) => {
  for (const item of array) {
    if (requiredFields.some(field => !item[field])) {
      return false
    }
  }
  return true
}

export const checkArrayNoRequiredItems = (array, requiredFields) => {
  for (const item of array) {
    // 检查是否是复杂结构 = ifelse嵌套多层
    if (item.inputList && item.ifType) {
      for (const innerItem of item.inputList) {
        if (requiredFields.some(field => !innerItem[field])) {
          return false
        }
      }
    } else if (requiredFields.some(field => !item[field])) {
      // 简单结构
      return false
    }
  }
  return true
}

/* array检查重复 输入 不能重复变量名 */
export const checkArrayItemsRepeat = (array, requiredFields) => {
  const fieldValues = new Map()
  for (const item of array) {
    // 检查对象不是空的
    for (const field of requiredFields) {
      if (!item[field] && item[field] !== 0) {
        console.error(`Missing or empty field: ${field}`)
        return false
      }
      // 如果有required
      if (item.required && typeof item.required === 'boolean') {
        if (!item[field]) {
          console.error(`Required field is missing or empty: ${field}`)
          return false
        }
      }
      // 检查重复
      if (fieldValues.has(field)) {
        if (fieldValues.get(field).has(item[field])) {
          console.error(`Duplicate value found for field: ${field} with value: ${item[field]}`)
          return false
        } else {
          fieldValues.get(field).add(item[field])
        }
      } else {
        fieldValues.set(field, new Set([item[field]]))
      }
    }
  }

  return true
}
/**
 * 检查数组中指定字段是否存在重复值。
 *
 * @param {Array} array - 包含对象的数组，每个对象代表一行数据。
 * @param {String} field - 要检查重复的字段名。
 * @returns {Boolean} 如果没有重复返回 true，否则返回 false 并打印错误信息。
 */
export const checkFieldDuplicates = (array, field) => {
  const seenValues = new Set()
  for (const item of array) {
    if (item[field] !== undefined && item[field] !== null) {
      if (seenValues.has(item[field])) {
        console.error(`Duplicate value found for field: ${field} with value: ${item[field]}`)
        return false
      }
      seenValues.add(item[field])
    } else {
      console.warn(`Missing or empty field: ${field} in item`, item)
    }
  }
  return true
}

/* message */
export const checkArrayMessFun = type => {
  showMessage({
    content: '存在校验失败的节点，请检查并配置后，重新试运行',
    type
  })
}

// 提供给运行时快速获取开始节点
export function findStartVariables(flowVariables = {}) {
  for (const key in flowVariables) {
    if (flowVariables[key].type === 'start') {
      return flowVariables[key]
    }
  }
  return undefined
}

// 快速获取用户input中的data信息
export function getUserInputsInfo(inputData) {
  if (!inputData) {
    return []
  }
  const inputObj = Object.values(inputData).map((item: any) => item.data)?.[0]
  return objToRunInfoArray(inputObj)
}

// obj转runResult数组
export const objToRunInfoArray = (obj: Node) => {
  if (!obj) return []

  return Object.keys(obj).map(key => {
    return {
      variable: key,
      value: obj[key]
    }
  })
}
/* 数组转obj key value */
export function arrayToObject(arr) {
  // 使用 reduce 方法遍历数组并构建对象
  return arr.reduce((accumulator, currentValue) => {
    accumulator[currentValue.variable] = currentValue.value
    return accumulator
  }, {}) // 初始值为空对象 {}
}

/* 
检查数组有效判断 

start     开始
end       结束
llm       大模型 
Tool      插件
Intend    意图识别
IfElse    选择器

参数：      
    inputList   开始
    outputs     结束
*/
export const checkNodeValidity = (node, nodeType) => {
  console.log('checkNodeValidity:', nodeType, node)
  if (!node || !nodeType) {
    return false
  }

  switch (nodeType) {
    case BlockEnum.LLM:
      return (
        !!node.model &&
        !!node.callWord &&
        !!node.callWord.trim() &&
        node.callWord.length < INPUT_CONSTRAINTS.CALL_WORD_MAX_LENGTH &&
        !!node.userInput &&
        !!node.userInput.trim() &&
        node.userInput.length < INPUT_CONSTRAINTS.CALL_WORD_MAX_LENGTH &&
        checkFieldDuplicates(node.inputList, 'variable') &&
        checkArrayNoRequiredItems(node.inputList, ['valuet', 'variable', 'type'])
      )
    case BlockEnum.Tool:
      return (() => {
        const list = node.inputList.filter(item => item.required)
        return checkArrayNoRequiredItems(list, ['valuet', 'variable', 'type'])
      })()
    case BlockEnum.Intend:
      return (
        !!node.model &&
        checkFieldDuplicates(node.inputList, 'variable') &&
        checkArrayNoRequiredItems(node.inputList, ['valuet', 'variable', 'type']) &&
        checkFieldDuplicates(node.recognizeList, 'variable') &&
        checkArrayNoRequiredItems(node.recognizeList, ['variable'])
      )
    case BlockEnum.IfElse:
      return checkArrayNoRequiredItems(node.ifList, ['value', 'variable', 'type', 'conditions'])
    case BlockEnum.End:
      if (node.outputType === 'text') {
        if (!node.outputText || !node.outputText.trim()) {
          return false
        }
        if (node.outputText.length > INPUT_CONSTRAINTS.AGENT_RECOVERY_MAX_LENGTH) {
          return false
        }
        return checkArrayItems(node.outputs, ['variable', 'value'])
      } else {
        return checkArrayItems(node.outputs, ['variable', 'value']) && checkArrayItemsRepeat(node.outputs, ['variable'])
      }
    case BlockEnum.Start:
      return (
        checkArrayItems(node.variables, ['variable', 'label']) && checkArrayItemsRepeat(node.variables, ['variable'])
      )
    case BlockEnum.KnowledgeRetrieval:
      return (
        checkArrayItems(node.inputList, ['variable', 'valuet']) &&
        !!node.knowledgeList &&
        node.knowledgeList.length !== 0 &&
        node.knowledgeList.length <= INPUT_CONSTRAINTS.KNOWLEDGE_MAX_CONT
      )
    case BlockEnum.Code:
      return  checkArrayItems(node.inputList, ['variable', 'valuet']) &&
        checkArrayItemsRepeat(node.outputList, ['variable'])
    case BlockEnum.DocExtractor:
      return checkDefaultRequiredArrayItems(node.inputList, ['variable', 'valuet'])  
      && checkArrayItemsRepeat(node.inputList, ['variable'])
    case BlockEnum.Iteration:
      return checkDefaultRequiredArrayItems(node.inputList, ['variable', 'valuet'])
    case BlockEnum.IterationEnd:
        return checkDefaultRequiredArrayItems(node.outputList, ['variable', 'valuet'])
    case BlockEnum.HttpRequest:
      return node.url
    case BlockEnum.TextConcatenation:
      return checkDefaultRequiredArrayItems(node.inputList, ['variable', 'value'])
    case BlockEnum.Loop:
      // todo
      return checkDefaultRequiredArrayItems(node.inputList, ['variable', 'valuet']) 
      &&  checkDefaultRequiredArrayItems(node.filter?.rules, ['variable', 'operation'])  
      && checkArrayItemsRepeat(node.inputList, ['variable'])
    case BlockEnum.VarUpdate:
      return checkDefaultRequiredArrayItems(node.inputList, ['variable']) && checkArrayItemsRepeat(node.inputList, ['variable'])
    case BlockEnum.List:
      return checkDefaultRequiredArrayItems(node.inputList, ['variable', 'value'])
    default:
      return true
  }
}

/**
 * 运行及发布前，检查所有节点的连接配置
 */
export const checkAllLinkConfig = (nodes, edges) => {
  /* 判断node ege */
  if (edges.length === 0) {
    return '校验失败，节点之间不能没有连线内容'
  }
  if (nodes.length < 3) {
    return '校验失败，必须存在一个可运行节点'
  }
  if (nodes.length > INPUT_CONSTRAINTS.RUN_PANDL_NODE_CONT) {
    return `校验失败，节点最大限制为${INPUT_CONSTRAINTS.RUN_PANDL_NODE_CONT}`
  }

  const sourceIds = new Set<string>(edges.flatMap(edge => [edge.source]))
  const targetIds = new Set<string>(edges.flatMap(edge => [edge.target]))

  // 有输入的节点
  const sourceFilteredNodes = nodes.filter(node => sourceIds.has(node.id)).concat(['start'])
  const targetFilteredNodes = nodes.filter(node => targetIds.has(node.id)).concat(['end'])

  /* 判断选择器 意图识别 多个选项没连线 提示报错 */
  const verifyNode = specificNodejudgment(nodes, edges)

  if (verifyNode === '请检查') {
    return '校验失败，存在未连接的节点'
  }

  // 获取下迭代器节点 */
  const iterationNodes = nodes.filter(node => node.data.type === BlockEnum.Iteration || node.data.type === BlockEnum.Loop)
  const iterationNodesCount = iterationNodes.length
  if (sourceFilteredNodes.length !== nodes.length - iterationNodesCount) {
    return '校验失败，存在未连接的节点'
  }

  if (targetFilteredNodes.length !== nodes.length - iterationNodesCount) {
    return '校验失败，存在未连接的节点'
  }
  return ''
}

function specificNodejudgment(nodes, edges) {
  // 提取所有需要检查的id
  const listIds = nodes.reduce((acc, item) => {
    if (item.data.type === 'if-else') {
      item.data.ifList.forEach(ifItem => acc.push(ifItem.case_id))
      acc.push('right_handle_' + item.data.id)
    } else if (item.data.type === 'intend' && item.data.recognizeList) {
      item.data.recognizeList.forEach(recognizeItem => acc.push(recognizeItem.id))
      acc.push('right_handle_' + item.data.id)
    }
    return acc
  }, [])

  // 检查每个id是否存在于edges的source或sourceHandle中
  for (const listId of listIds) {
    const found = edges.some(edge => edge.source === listId || edge.sourceHandle === listId)
    if (!found) {
      console.log(`ID ${listId} 没有在edges的source或sourceHandle属性中找到`)
      return '请检查'
    }
  }

  return '' // 所有id都找到了
}

function isValidValueSelector(node: any, id: string, variable: string, flowVariables: any): boolean {
  const targetNode = flowVariables[id]
  if (targetNode.type === BlockEnum.Start) {
    return targetNode && targetNode.variables?.some(v => v.variable === variable)
  }
  return !!targetNode
}

function clearItemValue(item: any): void {
  item.value = undefined
  item.value_selector = undefined
}

/**
 * 1、更新所有的溯源信息，当溯源节点，或者溯源变量不在溯源节点中时value和value_selector
 * 2、避免频繁触发，只在在两种情况触发移除：
 * 1）、运行前进行关联校验检查的根据nodes和edges进行移除
 * 2）、点击node节点获取source信息时
 * 传入nodeId时只更新对应节点值，不传nodeId更新所有
 */
export function removeUnreachableInfo(nodeId: string, nodes: any[], edges: any[], flowVariables: any): any {
  console.log('>>> 移除溯源信息 nodeId, edges, nodes, flowVariables: ', nodeId, edges, nodes, flowVariables)

  const newFlowVariables = cloneDeep(flowVariables)
  const processNode = (node: any) => {
    if (node.type !== BlockEnum.Start) {
      const sources = findSources(node.id, edges).filter((id: string) => flowVariables[id])
      console.log('------sources---------', node.title, sources)

      const itemsToCheck = node.outputs || node.inputList

      if (!itemsToCheck || itemsToCheck.length === 0) {
        return
      }

      for (const item of itemsToCheck) {
        if (Array.isArray(item.value_selector) && item.value_selector.length > 0) {
          const [id, variable] = item.value_selector
          if (!sources.includes(id) || !isValidValueSelector(node, id, variable, newFlowVariables)) {
            clearItemValue(item)
          }
        }
      }
    }
  }

  if (nodeId) {
    const node = newFlowVariables[nodeId]
    if (node) {
      processNode(node)
    }
  } else {
    for (const key in newFlowVariables) {
      if (newFlowVariables.hasOwnProperty(key)) {
        processNode(newFlowVariables[key])
      }
    }
  }

  return newFlowVariables
}

// 拖拽插件 点击选择 数据构建
export const toolDiaSaveFun = (defData, data) => {
  // 输出列表
  const outputList = [
    {
      variable: 'output',
      value: '插件输出',
      type: 'string',
      value_selector: []
    }
    // tree
    // {
    //   variable: 'output',
    //   value: '大模型输出111',
    //   type: 'string',
    //   value_selector: [],
    //   children: [
    //     {
    //       variable: 'subOutput',
    //       value: '子输出111',
    //       type: 'string',
    //       value_selector: [],
    //       children: []
    //     }
    //   ]
    // }
  ]

  // 输入
  let inputList = []

  try {
    if (data?.extra) {
      const { parameters = [] } = JSON.parse(data.extra)
      inputList = parameters.map(item => ({
        variable: item.name,
        type: item.schema.type === 'string' ? 'input' : 'cite',
        value_selector: [],
        value: '',
        required: item.required,
        // 选项为默认 - 显示
        defaultName: item?.schema?.default
      }))
    }
  } catch (error) {
    console.error('解析 extra 数据失败:', error)
  }

  return {
    ...defData,
    model: {
      ...defData.model,
      logo: data.logo,
      // desc: data.desc,
      id: data.id,
      name: data.name
    },
    desc: data.desc,
    outputList,
    inputList,
    parent_tool_id: data.parent_tool_id
  }
}

export function getFirstItem(arr) {
  return arr && arr.length ? arr[0] : ''
}

/* workflow/detail初始化数据 - 知识库数据更新同步 = knowledge_list */
export const knowledgeListUpdate = (flow, knowledge_list) => {
  // id映射加速查找
  const knowledgeMap = knowledge_list.reduce((acc, item) => {
    acc[item.id] = item
    return acc
  }, {})
  flow.graph.nodes.forEach(node => {
    if (node.data.type === 'qa_retriever') {
      node.data.knowledgeList = node.data.knowledgeList.map(knowItem => {
        const updatedItem = knowledgeMap[knowItem.id]
        if (updatedItem) {
          return {
            ...knowItem,
            description: updatedItem.description,
            icon: updatedItem.icon,
            name: updatedItem.name
          }
        }
        return knowItem
      })
    }
  })
  return flow
}
